package com.example.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ArrayUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.entity.Sign;
import com.example.entity.StudentSign;
import com.example.entity.User;
import com.example.mapper.SignMapper;
import com.example.mapper.StudentSignMapper;
import com.example.mapper.UserMapper;
import com.example.service.SignService;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Service
public class SignServiceImpl extends ServiceImpl<SignMapper, Sign> implements SignService {

    @Autowired
    private StudentSignMapper studentSignMapper;
    @Autowired
    private UserMapper userMapper;

    //设定线程池数量
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(10);

    @Override
    public HashMap<String,Object> generateQRCode(Sign sign) {
        HashMap<String, Object> map = new HashMap<>();
        String uuid = UUID.randomUUID().toString().replace("-","");
        Sign sign1 = new Sign();
        sign1.setId(uuid);
        sign1.setClassCode(sign.getClassCode());
        sign1.setSignKey(sign.getSignKey());
        sign1.setValidityPeriod(sign.getValidityPeriod());
        this.save(sign1);
        Sign signInfo = this.getById(uuid);
        map.put("sign",uuid);
        map.put("signInfo",signInfo);


        long validityPeriodInMillis = Integer.parseInt(sign.getValidityPeriod())*60* 1000L;

        // 调度延迟任务，在有效期结束后执行
        scheduler.schedule(() -> {
            // 在任务执行时更新数据库中的签到信息
            updateSignStatus(uuid);
        }, validityPeriodInMillis, TimeUnit.MILLISECONDS);


        return map;

    }

    @Override
    public HashMap<String, Object> studentSignIn(StudentSign student, String signId) throws ParseException {
        HashMap<String, Object> map = new HashMap<>();

        HashMap<String, String> resuleMap = checkValidityPeriod(signId, student);
        //完成签到校验
        if (!resuleMap.get("resultCode").equals("0")){
            if (resuleMap.get("resultCode").equals("1")){
                map.put("type",1);
                map.put("message","当前签到码错误");
            }else if (resuleMap.get("resultCode").equals("2")){
                map.put("type",2);
                map.put("message","当前签到码已过期");
            }else if(resuleMap.get("resultCode").equals("3")){
                map.put("type",3);
                map.put("message","当前设备已完成签到");
            }else if(resuleMap.get("resultCode").equals("4")){
                map.put("type",4);
                map.put("message","请输入正确学号和姓名");
            }
            return map;
        }
        //通过校验后执行相关签到逻辑
        LambdaQueryWrapper<StudentSign> wrapper = new LambdaQueryWrapper<>();
        student.setSignId(signId);
        student.setUserIp(resuleMap.get("userIp").toString());
        student.setUniqueCode(resuleMap.get("uniqueCode").toString());
        studentSignMapper.insert(student);
        map.put("type",0);

        map.put("message","签到成功");

        return map;
    }

    @Override
    public Sign getNewSignStatus(String classCode) {
        List<Sign> list = this.lambdaQuery().eq(Sign::getClassCode, classCode).orderByDesc(Sign::getCreateTime).list();
        Sign sign = null;
        if (list!=null && !list.isEmpty()){
            sign =  list.get(0);
        }

        return sign;
    }

    /**
     * 检测签到码的正确性和有效性
     * @param signId
     * @param student
     * @return
     */
    public  HashMap<String, String> checkValidityPeriod(String signId,StudentSign student) throws ParseException {
        HashMap<String, String> map = new HashMap<>();
        Sign sign = this.getById(signId);
        boolean isRight = sign.getSignKey().equals(student.getSignKey());
        if (!isRight){
            map.put("resultCode","1");//"当前签到码错误"
            return map;
        }

        if (sign.getStillUse()==0){
            map.put("resultCode","2");//"当前签到码已过期"
            return map;
        }

        //判断当前签到用户是否存在该班级中
        LambdaQueryWrapper<User> userWrapper = new LambdaQueryWrapper<>();
        userWrapper.eq(User::getAccount,student.getAccount())
                .eq(User::getUserName,student.getUserName())
                .eq(User::getClassCode,sign.getClassCode());
        User user = userMapper.selectOne(userWrapper);
        if (Objects.isNull(user)){
            map.put("resultCode","4");//"当前签到码已过期"
            return map;
        }

        //拼接ip和signId获得唯一码
        String userIp = getUserIp();
        String uniqueCode = userIp.replace(".","").concat(signId);
        LambdaQueryWrapper<StudentSign> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StudentSign::getUniqueCode,uniqueCode);
        boolean exists = studentSignMapper.exists(wrapper);
        if (exists){
            map.put("resultCode","3");//"当前设备已完成签到"
            return map;
        }





        map.put("resultCode","0");
        map.put("userIp",userIp);
        map.put("uniqueCode",uniqueCode);
        return map;

    }

    /**
     * 获取唯一码
     * @param
     * @return
     */
    public String getUserIp(){
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        // 获取远程IP地址
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        // 获取到多个ip时取第一个作为客户端真实ip
        if (StringUtils.isNotEmpty(ip) && ip.contains(",")) {
            String[] ipArray = ip.split(",");
            if (ArrayUtils.isNotEmpty(ipArray)) {
                ip = ipArray[0];
            }
        }
        return ip;


    }

    /**
     * 有效期到后更新签到状态
     * @param uuid
     */
    public void updateSignStatus(String uuid){
        this.lambdaUpdate().eq(Sign::getId,uuid).set(Sign::getStillUse,0).update();

    }


    @Override
    public Sign getSignById(String sign) {
        return this.getById(sign);
    }
}
